package com.as3extensions.helpers
{
  import com.as3extensions.Template;
  
  public class StringHelper
  {
    public static function $w( string : * ) : Array
    {
      if ( !(string is String) ) return [];
      
      string = StringHelper.strip( string );
      
      return string ? string.split(/\s+/) : [];
    }
    
    public static function interpret( string : String ) : String
    {
      return string == null ? '' : string;
    }
    
    public static function gsub( source : String, pattern : RegExp, replacement : * ) : String
    {
      var prepareReplacement : Function = function( replacement : * ) : Function
      {
        trace( replacement );
        if ( replacement is Function ) return (replacement as Function)
        var template : Template = new Template(String(replacement));
        return function( match : Object ) : String { return template.evaluate(match); };
      };
      
      var replacementFunction : Function = prepareReplacement(replacement);
      
      var result : String = new String();
      
      while (source.length > 0) {
        var match : Array = source.match( pattern );
        
        if ( match ) {
          result += source.slice(0, match.index);
          result += StringHelper.interpret(replacementFunction(match));
          source  = source.slice(match.index + match[0].length);
        } else {
          result += source, source = '';
        }
      }
      return result;
    }
    
    public static function toQueryParams(string:String) : Object
    {
      var match:Array = StringHelper.strip(string).match(/([^?#]*)(#.*)?$/);
      var params:Object = {};
      
      if (!match) return params;

      var arrayOfParams:Array = match[1].split('&');
      for each( var pair:String in arrayOfParams )
      {
        var pairs:Array = pair.split('=');
        
        if (pairs[0]) {
          var key:String = pairs.shift();
          var value:String = pairs.length > 1 ? pairs.join('=') : pairs[0];
          
          params[key] = value;
        }
      }
      
      return params;
    }
    
    public static function strip( string : String ) : String
    {
      return string.replace(/^\s+/, '').replace(/\s+$/, '');
    }
    
    public static function truncate( string : String, length : int = 30, truncation : String = '...' ) : String
    {
      if ( string.length > length ) return string.slice(0, length - truncation.length) + truncation;

      return string;
    }

    public static function toArray( string : String ) : Array
    {
      return string.split('');
    }

    public static function camelize( string : String ) : String
    {
      var parts : Array  = string.split('-');

      if ( parts.length == 1 ) return parts[0];

      var camelized : String = string.charAt(0) == '-' ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1) : parts[0];

      for (var i : int = 1; i < parts.length; i++)
        camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);

      return camelized;
    }

    public static function underscore( string : String ) : String
    {
      return StringHelper.gsub( StringHelper.gsub( StringHelper.gsub( StringHelper.gsub(string, /::/, '/'), /([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}' ), /([a-z\d])([A-Z])/,'#{1}_#{2}'), /-/,'_').toLowerCase();
    }

    public static function dasherize( string : String ) : String
    {
      return StringHelper.gsub( string, /_/, '-' );
    }
    
    public static function startsWith( string : String, pattern : String ) : Boolean
    {
      return string.indexOf( pattern ) === 0;
    }

    public static function endsWith( string : String, pattern : String ) : Boolean
    {
      var delta : int = string.length - pattern.length;
      return delta >= 0 && string.lastIndexOf(pattern) === delta;
    }

    public static function empty( string : String ) : Boolean
    {
      return string == '';
    }

    public static function blank( string : String ) : Boolean
    {
      return (new RegExp(/^\s*$/)).test( string );
    }
    
    public static function interpolate( string : String, object : Object, pattern : RegExp = null ) : String
    {
      return new Template( string, pattern ).evaluate( object );
    }
  }
}